
package my.algorithms.mcorrea.datastructures;

/**
 *
 * @author mcorrea
 */
public class DoubleLinkedList<T> {
	
	private Node<T> head;
	private Node<T> tail;
	private int size = 0;
	
	public DoubleLinkedList(){}
	
	
	private void insert(T value){
		if(tail != null){
			Node<T> newNode = new Node<T>(null, tail, value);
			tail.setNext(newNode);
			tail = newNode;
		}else{
			head = new Node<T>(null, null, value);
			tail = head;
		}
		size++;
	}
	
	private boolean contains(T value){
		if(head!=null){
			Node<T> temp = head;
			while(temp.getValue() != value && temp.getNext()!=null){
				temp = temp.getNext();
			}
			if(temp.getValue() == value){
				return true;
			}else{
				return false;
			}			
		}else return false;
	}
	
	
	//remove first apperecne of the object value
	private void remove(T value){
		if(head !=null){
			Node<T> temp = head;
			while(temp.getValue() != value && temp.getNext()!=null){
				temp = temp.getNext();
			}
			if(temp.getValue() == value){
				if(temp.getNext()!=null){
					temp.getNext().setPrev(temp.getPrev());
				}
				if(temp.getPrev()!=null){
					temp.getPrev().setNext(temp.getNext());
				}else{
					//head
					head = temp.getNext();
				}
				temp.setNext(null);
				temp.setPrev(null);
				temp = null; 
			}
			size--;
		}
	
	}
	
	public int size(){
		return size;
	}
	
	@Override
	public String toString(){
		if(head!=null){
			String list = "[ "+head.getValue()+" ";
			Node<T> temp = head;
			while(temp.getNext()!=null){
				temp = temp.getNext();
				list += temp.getValue()+" ";
			}
			return list+" ]";
		}else return "List empty";
	
	}
	
	
	protected class Node<T>{
		
		private Node<T> next;
		private T value; 
		private Node<T> prev;
		
		public Node(Node<T> next, Node<T> prev, T value){
			this.next = next;
			this.prev = prev;
			this.value = value;
		}

		public Node<T> getNext() {
			return next;
		}

		public void setNext(Node<T> next) {
			this.next = next;
		}

		public Node<T> getPrev() {
			return prev;
		}

		public void setPrev(Node<T> prev) {
			this.prev = prev;
		}

		public T getValue() {
			return value;
		}

		public void setValue(T value) {
			this.value = value;
		}
	
	}
	
	
	
	public static void main(String args[]){
		DoubleLinkedList<Integer> mylist = new DoubleLinkedList<Integer>();
		mylist.insert(1);
		mylist.insert(2);
		mylist.insert(3);
		mylist.insert(4);
		System.out.println(mylist);
		
		System.out.println(mylist.contains(1));
		System.out.println(mylist.contains(4));
		System.out.println(mylist.contains(12));
	
		
		mylist.remove(1);
		System.out.println(mylist);
		mylist.remove(2);
		System.out.println(mylist);
		System.out.println("size="+mylist.size());
		mylist.insert(1);
		mylist.insert(2);
		System.out.println(mylist);
		
		System.out.println("size="+mylist.size());
	
	}
	
}
